<?

	require_once PKG_DIR.'/Fmgr/ClassInterfaces.php';

	final class Package_Fmgr0v0r01 extends _smuoiPackage implements Package_Fmgr{

####	INSTANTIATION AND LOCAL fmrp CACHE
		
		private $CACHE = array();
		
		function cache($rsrc){
			$this->CACHE[$rsrc->fmrp] = $rsrc;
		}
		
		function uncache($rsrc){
			unset($this->CACHE[$rsrc->fmrp]);
		}
		
		function get_cached($fmrp){
			return isset($this->CACHE[$fmrp]) ? $this->CACHE[$fmrp] : false;
		}
		
		function instantiateRow($data, $res=false){
			$this->cache($rsrc = parent::instantiateRow($data, $res));
			return $rsrc;
		}
		
		// select() is a shortcut to db()->select and always returns fully instantiated objects
		function select($fields, $where, $orderby='', $limit=''){
			$table = $this->table('files');
			if(!$results = $this->al()->select($fields, $table, $where, $orderby, $limit)) return false;
			foreach($results as $result) $objects[] = $this->db->register($result, $table);
			return (count($objects) > 1) ? $objects : $objects[0];
		}
		
		// If a root directory doesn't yet exist, this sets it up
		private function initRootDir($cname){
			$class = $this->apply_namespace($cname);
			require_once $this->path_to_dataclass($cname);
			$RDIR = new $class(false, $this, array('own'=>$this->domain()->own, 'grp'=>$this->domain()->grp));
			$RDIR->commit();
			$RDIR->init_uniq();
			// in fact let's set them all up
			foreach($this->root_dirs as $cname) $this->open(strtolower($cname).":/");
			return $RDIR;
		}
	
####	RESOURCE RETRIEVAL

		// open() : by contextual protocol
		// docs:/.htaccess (or simply /.htaccess)
		// desk:/myapplication/ascreen
		// temp:/Drafts
		function open($req){
			if(!is_string($fmrp = $this->read_request_uri($req))) return $fmrp;
			if($rsrc = $this->get_cached($fmrp)) return $rsrc;
			if($rsrc = $this->select('*', array('fmrp'=>$fmrp, 'xst'=>1))) return $rsrc;
			return ($cname = $this->fmrp_rd_class($fmrp)) ? $this->initRootDir($cname) : false;
		}
		
		function get($k){
			return $this->open($k);	
		}
		
		function read_request_uri($ru){
			if(strpos($ru, ':') != 4) $ru = "docs:/".smuoi_clean_request_uri($ru);
			elseif(substr($ru, 0, 4) == 'home'){
				if(!$u = usr()) return false;
				$ru = "desk:/users/".smuoi_clean_request_uri($u->name.substr($ru, 5));
				if($u->home !== $this->dom_id()) return smrf($u->home."::$ru");
			}else{
				$a = explode(':', $ru);
				$ru = $a[0].':/'.smuoi_clean_request_uri($a[1]);
			}
			return $ru;
		}

####	KEY CLASSES OF RESOURCE
		
		//	rootdir() : returns full path to dir given the directory's rdk (root dir key), a strtolower representation of its classname	
		function rootdir($rdk='docs'){
			return realpath($this->domain()->getDir($rdk));
		}
			
		//	$root_dirs : Classes of directory with no parent
		private $root_dirs = array('Docs', 'Desk', 'Temp');
		private $rd_paths;
		
		//	rootdirs() : returns an array of all the root_dir paths
		function rd_paths(){
			if(is_null($this->rd_paths)) foreach($this->root_dirs as $k) $this->rd_paths[$k] = $this->rootdir($k);
			return $this->rd_paths;
		}
		
		// 	$unique_first_dirs : Classes of directory which are unique and 
		//	live within a root directory. 
		private $unique_first_dirs = array(
			'Trash'=>'Desk',
			'Scripts'=>'Desk',
			'Users'=>'Desk',
			'Thumbs'=>'Temp',
			'Drafts'=>'Temp'
		);
		private $ud_paths;

		// 	uniqquedirs : returns an array of paths of all root_dirs and unique_first_dirs
		function ud_paths(){
			if(is_null($this->ud_paths)){
				$a = $this->rd_paths();	
				foreach($this->unique_first_dirs as $k=>$v) $this->ud_paths[$k] = $a[$v].'/'.strtolower($k);
			}
			return $this->ud_paths;
		}
		
		// 	$unique_first_files : as above, but files 
		private $unique_first_files = array(
			'Home'=>'Desk',
			'Docroot'=>'Desk'
		);
		private $uf_paths;
		
		// 	uniqquefiles : returns an array of paths of all unique_first_files
		function uf_paths(){
			if(is_null($this->uf_paths)){
				$a = $this->rd_paths();	
				foreach($this->unique_first_files as $k=>$v) $this->uf_paths[$k] = $a[$v].'/'.strtolower($k);
			}
			return $this->uf_paths;
		}
		
		function Longtext(){
			return $this->db->package('Longtext');	
		}
		
		function fmrp_rd_class($fmrp){
			$a = explode(':/', $fmrp);
			if(@$a[1]) return false;
			$cname = ucfirst($a[0]);
			return in_array($cname, $this->root_dirs) ? $cname : false;
		}
		
####	NEW RESOURCE PREPARATION
		
		function read_coldfile($fp){
			if(!file_exists($fp) || !is_readable($fp)) return false;
			if(is_dir($fp)){
				$r['dir'] = 1;
				$r['class'] = $this->read_dir_class($fp);
				return $r;
			}
			$r = $this->get_fileinfo($fp);
			$r['class'] = $this->read_file_class($fp, $r);
			$r['dir'] = 0;
			$r['xst'] = 1;
			return $r;
		}
		
		function get_fileinfo($fp){
			require_once $this->path_to_libclass('FileInfo');
			return Fmgr0v0r01_FileInfo::read($fp);
		}
		
		function read_dir_class($fp){
			$u = $this->ud_paths();
			foreach($u as $k=>$v) if($fp == $v) return $k;
			// Else if child of Thumbs or Drafts...
			$dn = dirname($fp);
			if($dn == $u['Drafts']) return 'draft';
			if($dn == $u['Thumbs']) return 'thumb';
			return is_link($fp) ? 'symdir' : 'dir';
		}
		
		function app_classes(){
			return array('lnk', 'mnt', 'app');	
		}
		
		function read_file_class($fp, $m=false){
			$u = $this->uf_paths();
			foreach($u as $k=>$v) if($fp == $v) return $k;
			if(!$m) $m = $this->get_fileinfo($fp);
			// if it's text on the desktop test if is an app
			// is_text_file is potentially expensive operation so we only care if filesize is < 512
			if($m['filesize'] < 512){
				if(!$m['filesize']) return 'text';
				if(is_text_file($fp)){
					if(!$m['xtn'] && (dirname($fp) == $this->rootdir('desk')) && (is_array($a = @parse_ini_file($fp)) && (!empty($a)))){
						if(isset($a['app_class']) && in_array($a['app_class'], $this->app_classes())) return $a['app_class'];
						return 'app';
					}
					if($m['class'] == 'file') return 'text';
				}
			}
			return $m['class'];
		}
		
		function is_fileclass($class){
			if(!$this->is_valid_dataclass($class)) return false;
			if($class[0] == strtoupper($class[0])) return false;
			if(in_array($class, array('dir', 'draft', 'symdir', 'thumb'))) return false;
			return true;
		}
		
		function fp_fmrp($fp){
			$fmrp = false;
			foreach($this->rd_paths() as $k=>$v){
				if(substr($fp, 0, strlen($v)) !== $v) continue;	
				$path = substr($fp, strlen($v));
				$fmrp = strtolower($k).($path ? ':' : ':/').$path;
				break;
			}
			return ($fmrp) ? $fmrp : false;
		}
		
		function fmrp_fp($fmrp){
			list($dom, $sig, $path) = parse_smrf($fmrp);
			return $this->rootdir($sig).$path;
		}
				
		function build_file($fp, $set=false){
			if(!$rc = $this->read_coldfile($fp)) return false;
			$o = new obj;
			if($set) $o->set($set);
			$o->set($rc);
			$tb = $this->table('files');
			if($o->fmrp = $this->fp_fmrp($fp)){
				// If there's a file in the database with the same path, no matter what it is
				// you were looking for it
				if($data = $this->al()->select('*', $tb, array('fmrp'=>$o->fmrp))){
					$data = array_merge($data[0], get_object_vars($o));
					return $this->db->register($data, $tb, 1, 1);
				}
			}
			if(!$o->dir){
				// If there's an orphaned file with the same checksum, you're getting it
				if($data = $this->al()->select('*', $tb, array('checksum'=>$o->checksum, 'xst'=>0), '`updated` DESC', 1)){
					$data = array_merge($data[0], get_object_vars($o));
					return $this->db->register($data, $tb, 1, 1);
				}
			}
			$o->set(
				'new', 1,
				'srcpath', $fp
			);
			return $o;
		}
	
####	INSTANCEOF TESTS (This namespace)
		
		function is_fmgr_rsrc($o){
			return $this->test_instanceof($o, '_common');
		}
		
		function is_fmgr_dir($o){
			return $this->test_instanceof($o, 'dir');
		}
		
		function is_fmgr_mnt($o){
			return $this->test_instanceof($o, 'mnt');
		}
		
		function is_fmgr_file($o){
			return $this->test_instanceof($o, 'file');
		}
		
		function is_fmgr_app($o){
			return $this->test_instanceof($o, 'app');
		}
		
		function is_fmgr_image($o){
			return $this->test_instanceof($o, 'image');
		}
		
		function is_fmgr_text($o){
			return $this->test_instanceof($o, 'text');
		}
	}
?>